const { sys_dept_model: SysDeptModel } = require('../models');
const DateUtils = require('../utils/dateUtils');
const { v4: uuidv4 } = require('uuid');
const { Op } = require('sequelize');
const { realDelete } = require('../config/system');

class DeptService {
    /**
     * 创建部门
     * @param {Object} deptData 部门数据
     */
    async createDept(deptData) {
        // 检查是否存在相同的部门名称
        const existingDept = await SysDeptModel.findOne({
            where: { name: deptData.name }
        });
        if (existingDept) {
            throw new Error('存在相同的部门名称');
        }

        // 根据parentId查询父部门
        let treePath = '0';
        if (deptData.parentId) {
            const parentDept = await SysDeptModel.findOne({
                where: { id: deptData.parentId }
            });
            if (parentDept) {
                treePath = parentDept.treePath ? `${parentDept.treePath},${parentDept.id}` : String(parentDept.id);
            }
        }

        return await SysDeptModel.create({
            ...deptData,
            treePath: treePath,
            code: deptData.code || `DEPT_${uuidv4().replace(/-/g, '').substring(0, 8).toUpperCase()}`,
            isDeleted: 0,
            status: deptData.status != null? deptData.status : 1,
            createTime: DateUtils.getCurrentTime(),
            updateTime: DateUtils.getCurrentTime(),
        });
    }

    /**
     * 更新部门
     * @param {number} id 部门ID
     * @param {Object} deptData 部门数据
     */
    async updateDept(id, deptData) {
        const existingDept = await SysDeptModel.findOne({
            where: { id }
        });
        if (!existingDept) {
            throw new Error('部门数据不存在');
        }

        await existingDept.update({
            ...deptData,
            update_time: DateUtils.getCurrentTime()
        });

        return existingDept;
    }

    /**
     * 删除部门
     * @param {number} id 部门ID
     */
    async deleteDept(id) {
        const dept = await SysDeptModel.findByPk(id);
        if (!dept) {
            throw new Error('部门数据不存在');
        }
        if (realDelete) {
            // 真实删除
            await dept.destroy();
        } else {
            // 软删除
            await dept.update({
                is_deleted: 1,
                update_time: DateUtils.getCurrentTime()
            });
        }
    }

    /**
     * 获取部门详情
     * @param {number} id 部门ID
     */
    async getDeptById(id) {
        return await SysDeptModel.findOne({
            where: { id, is_deleted: 0 }
        });
    }

    /**
     * 获取部门列表
     * @param {Object} query 查询条件
     */
    async getDeptList(query) {
        const { name, status, pageNum = 1, pageSize = 10 } = query;
        const where = { is_deleted: 0 };

        if (name) {
            where.name = { [Op.like]: `%${name}%` };
        }
        if (status !== undefined) {
            where.status = status;
        }

        return await SysDeptModel.findAndCountAll({
            where,
            offset: (pageNum - 1) * pageSize,
            limit: parseInt(pageSize),
            order: [['sort', 'ASC'], ['create_time', 'DESC']]
        });
    }

    /**
     * 获取部门树形结构
     * @param {Object} query 查询条件
     */
    async getDeptTree(query = {}) {
        const { keywords, status } = query;
        const where = { isDeleted: 0 };
        let allDepts = [];

        // 如果有查询条件，先查询匹配的部门
        if (keywords || status !== undefined) {
            const matchedDepts = await SysDeptModel.findAll({
                where: {
                    ...where,
                    ...(keywords && { name: { [Op.like]: `%${keywords}%` } }),
                    ...(status !== undefined && { status })
                },
                order: [['sort', 'ASC']]
            });

            // 收集所有匹配部门的ID和上级部门ID
            const deptIds = new Set();
            matchedDepts.forEach(dept => {
                deptIds.add(dept.id);
                if (dept.treePath) {
                    dept.treePath.split(',').forEach(pid => deptIds.add(pid));
                }
            });

            // 查询所有相关部门（包括匹配的部门和它们的上级部门）
            allDepts = await SysDeptModel.findAll({
                where: {
                    ...where,
                    id: { [Op.in]: Array.from(deptIds) }
                },
                order: [['sort', 'ASC']]
            });
        } else {
            // 如果没有查询条件，查询所有部门
            allDepts = await SysDeptModel.findAll({
                where,
                order: [['sort', 'ASC']]
            });
        }

        return this.buildDeptTree(allDepts);
    }

    /**
     * 构建部门树形结构
     * @param {Array} depts 部门列表
     * @param {string} parentId 父级ID
     */
    buildDeptTree(depts) {
        // 使用Map优化查找效率
        const deptMap = new Map();
        
        // 第一步：先将所有节点存入Map
        depts.forEach(dept => {
            const node = dept.toJSON();
            deptMap.set(node.id, node);
        });
        
        // 第二步：构建树形结构
        const tree = [];
        deptMap.forEach(node => {
            const { parentId } = node;
            
            if (!parentId || parentId == '0') {
                // 根节点直接加入树中
                tree.push(node);
            } else {
                // 将子节点添加到父节点的children数组
                const parentNode = deptMap.get(parentId);
                if (parentNode) {
                    if (!parentNode.children) {
                        parentNode.children = [];
                    }
                    parentNode.children.push(node);
                } else {
                    // 如果找不到父节点，作为根节点处理
                    tree.push(node);
                }
            }
        });
        
        return tree;
    }

    /**
     * 获取部门下拉选项
     */
    async getDeptOptions() {
        const where = { 
            is_deleted: 0,
            status: 1,
         };
        const depts = await SysDeptModel.findAll({
            where,
            order: [['sort', 'ASC']]
        });

        return this.buildDeptOptionsTree(depts);
    }

    /**
     * 构建部门下拉选项树形结构
     * @param {Array} depts 部门列表
     * @param {string} parentId 父级ID
     */
    buildDeptOptionsTree(depts, parentId = '0') {
        const tree = [];
        depts.forEach(dept => {
            if (dept.parentId == parentId) {
                const node = {
                    value: dept.id,
                    label: dept.name,
                    tag: dept.code,
                    children: this.buildDeptOptionsTree(depts, dept.id)
                };
                if (node.children.length === 0) {
                    delete node.children;
                }
                tree.push(node);
            }
        });
        return tree;
    }
}

module.exports = new DeptService();